home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Technology Seed / ADC Seed CD - July 1999.toast / ColorSync / ColorSync 2.6 Mac SDK / Sample Code / DemoCMM / DemoCMM.c next >
Encoding:
C/C++ Source or Header  |  1999-04-12  |  40.4 KB  |  1,494 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        DemoCMM.c
  3.  
  4.     Contains:    Demo CMM Component for ColorSync 2.x
  5.                 
  6.                 This is a very simple CMM - so simple in fact that the only thing
  7.                 it uses from a profile is its colorspace.
  8.                 
  9.                 If the first (source) profile is RGB and the last (dest) profile
  10.                 is CMYK, then this CMM uses the simple "one minus" formula
  11.                 to convert from from RGB to CMYK.
  12.                 
  13.                 If the first (source) profile is CMYK and the last (dest) profile
  14.                 is RGB, then this CMM uses the inverse of the "one minus" formula
  15.                 to convert from from CMYK to RGB.
  16.  
  17.                 If the first and the last profile are RGB or if the first and the 
  18.                 last profile are CMYK, then this CMM leaves the colors unchanged.
  19.                 
  20.     Version:    ColorSync 2 or later
  21.  
  22.     Written by:    David Hayward
  23.  
  24.     Copyright:    © 1998-1999 by Apple Computer, Inc., all rights reserved.
  25.  
  26.     Writers:
  27.         (DH)    David Hayward
  28.  
  29.     Change History (most recent first):
  30.  
  31.          <5>      2/1/99    DH        Added some CS2.6 features
  32.          <4>    10/20/98    DH        Fixed Win32 exports.
  33.          <2>    10/13/98    DH        Overhaul to build x-platform.
  34.          <1>     7/16/98    DH        First checked in.
  35.  
  36. */
  37.  
  38. #include <ConditionalMacros.h>
  39.  
  40. #if TARGET_OS_WIN32
  41.     #pragma warning (disable : 4068) // disable warnings for #pragma mark...
  42.     #if __MWERKS__
  43.         #include <x86_prefix.h>
  44.     #endif
  45.     #include <windows.h>
  46.     #undef  pascal
  47.     #define pascal
  48. #endif
  49.  
  50. #include <MacTypes.h>
  51. #include <Errors.h>
  52. #include <Endian.h>
  53. #include <MacMemory.h>
  54. #include <Gestalt.h>
  55. #include <Components.h>
  56. #include <CMMComponent.h>
  57.  
  58. #if TARGET_OS_MAC
  59. #include <math.h>
  60. #else
  61. #include <fp.h>
  62. #endif
  63.  
  64. #ifndef DEBUG
  65. #define DEBUG 0
  66. #endif
  67.  
  68. #define CMM_ENTRY        __declspec(dllexport) 
  69.  
  70. // Component version
  71. #define     kCMCodeVersion        1
  72. #define        kCMMVersion            ((CMMInterfaceVersion << 16) | kCMCodeVersion)
  73.  
  74. typedef void (*MatchOneProc) (UInt16* chan);
  75.  
  76.  
  77. // Component storage
  78. typedef struct
  79. {
  80.     ComponentInstance    ci;
  81.     OSType                srcSpace;
  82.     OSType                srcClass;
  83.     OSType                dstSpace;
  84.     OSType                dstClass;
  85.     MatchOneProc        proc;
  86. } CMMStorageRec, *CMMStoragePtr, **CMMStorageHdl;
  87. // Note that on Mac, CMMStorageHdl is a Handle
  88. // whereas on Win32, CMMStorageHdl is a ptr to a ptr
  89.  
  90.  
  91. // Match stuff
  92. typedef struct
  93. {
  94.     CMMStorageHdl        storage;
  95.     
  96.     UInt32                height;
  97.     UInt32                width;
  98.     
  99.     OSType                srcSpace;
  100.     UInt8*                srcBuf[4];
  101.     UInt32                srcChanBits;
  102.     UInt32                srcRowBytes;
  103.     UInt32                srcColBytes;
  104.     Boolean                srcSwap;
  105.     
  106.     OSType                dstSpace;
  107.     UInt8*                dstBuf[4];
  108.     UInt32                dstChanBits;
  109.     UInt32                dstRowBytes;
  110.     UInt32                dstColBytes;
  111.     Boolean                dstSwap;
  112.     
  113. } CMMMatchRec, *CMMMatchPtr, **CMMMatchHdl;
  114.  
  115.  
  116. // Technique for Native PPC Component function calls from Tech Note "QT05-Component Mgr 3.0"
  117. #if TARGET_CPU_PPC
  118.     #define CCFWS(storage,params,name)    CallComponentFunctionWithStorage(storage, params, &name##RD)
  119.     #define CCF(params,name)             CallComponentFunction(params, &name##RD)
  120.     #define INSTANTIATE_RD(name)        RoutineDescriptor name##RD = BUILD_ROUTINE_DESCRIPTOR(upp##name##ProcInfo, name)
  121. #else
  122.     #define CCFWS(storage,params,name)    CallComponentFunctionWithStorage(storage, params, (ComponentFunctionUPP)name)
  123.     #define CCF(params,name)            CallComponentFunction(params, (ComponentFunctionUPP)name)
  124. #endif
  125.  
  126.  
  127. // proc infos
  128. enum {
  129.     uppDoComponentOpenProcInfo = kPascalStackBased
  130.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  131.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentInstance))),
  132.     uppDoComponentCloseProcInfo = kPascalStackBased
  133.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  134.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  135.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ComponentInstance))),
  136.     uppDoComponentCanDoProcInfo = kPascalStackBased
  137.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  138.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short))),
  139.     uppDoComponentVersionProcInfo = kPascalStackBased
  140.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))),
  141.     uppDoComponentRegisterProcInfo = kPascalStackBased
  142.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))),
  143.     uppDoCMMInitProcInfo = kPascalStackBased
  144.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  145.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  146.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMProfileHandle)))
  147.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(CMProfileHandle))),
  148.     uppDoNCMMInitProcInfo = kPascalStackBased
  149.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  150.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  151.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMProfileRef)))
  152.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(CMProfileRef))),
  153.     uppDoCMMConcatInitProcInfo = kPascalStackBased
  154.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  155.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  156.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMConcatProfileSet*))),
  157.     uppDoNCMMConcatInitProcInfo = kPascalStackBased
  158.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  159.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  160.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NCMConcatProfileSet*)))
  161.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(CMConcatCallBackUPP)))
  162.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*))),
  163.     uppDoCMMMatchColorsProcInfo = kPascalStackBased
  164.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  165.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  166.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMColor*)))
  167.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(UInt32))),
  168.     uppDoCMMCheckColorsProcInfo = kPascalStackBased
  169.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  170.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  171.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMColor*)))
  172.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(UInt32)))
  173.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(UInt32*))),
  174.     uppDoCMMMatchBitmapProcInfo = kPascalStackBased
  175.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  176.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  177.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMBitmap*)))
  178.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(CMBitmapCallBackUPP)))
  179.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*)))
  180.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(CMBitmap*))),
  181.     uppDoCMMCheckBitmapProcInfo = kPascalStackBased
  182.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  183.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  184.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMBitmap*)))
  185.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(CMBitmapCallBackUPP)))
  186.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*)))
  187.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(CMBitmap*)))
  188. };
  189.  
  190.  
  191. // function prototypes
  192. #if TARGET_OS_MAC
  193. pascal ComponentResult main                            (ComponentParameters *params, Handle storage);
  194. static pascal ComponentResult DoComponentOpen        (ComponentInstance self);
  195. static pascal ComponentResult DoComponentClose        (CMMStorageHdl storage, ComponentInstance self);
  196. static pascal ComponentResult DoComponentCanDo        (short selector);
  197. static pascal ComponentResult DoComponentVersion    (void);
  198. static pascal ComponentResult DoComponentRegister    (void);
  199. #endif
  200. static pascal CMError DoCMMInit                (CMMStorageHdl storage, CMProfileHandle srcProfile, CMProfileHandle dstProfile);
  201. static pascal CMError DoNCMMInit            (CMMStorageHdl storage, CMProfileRef srcProfile, CMProfileRef dstProfile);
  202. static pascal CMError DoCMMConcatInit        (CMMStorageHdl storage, CMConcatProfileSet* profileSet);
  203. static pascal CMError DoNCMMConcatInit        (CMMStorageHdl storage, NCMConcatProfileSet* profileSet, CMConcatCallBackUPP proc, void* refCon);
  204. static pascal CMError DoCMMMatchColors        (CMMStorageHdl storage, CMColor *colorBuf, UInt32 count);
  205. static pascal CMError DoCMMCheckColors        (CMMStorageHdl storage, CMColor *colorBuf, UInt32 count, UInt32 *gamutResult);
  206. static pascal CMError DoCMMMatchBitmap        (CMMStorageHdl storage, const CMBitmap * srcMap, CMBitmapCallBackUPP progressProc, void* refCon, CMBitmap* dstMap);
  207. static pascal CMError DoCMMCheckBitmap        (CMMStorageHdl storage, const CMBitmap * srcMap, CMBitmapCallBackUPP progressProc, void* refCon, CMBitmap* chkMap);
  208. static CMError         CheckStorage            (CMMStorageHdl storage);
  209. static void            MatchAll                (CMMMatchPtr pMatchInfo);
  210. static void MatchOne_RGB_CMYK    (UInt16* chan);
  211. static void MatchOne_CMYK_RGB    (UInt16* chan);
  212. static void MatchOne_RGB_XYZ    (UInt16* chan);
  213. static void MatchOne_XYZ_RGB    (UInt16* chan);
  214. static void MatchOne_RGB_LAB    (UInt16* chan);
  215. static void MatchOne_LAB_RGB    (UInt16* chan);
  216. static void MatchOne_XYZ_LAB    (UInt16* chan);
  217. static void MatchOne_LAB_XYZ    (UInt16* chan);
  218. static void MatchOne_XYZ_Gray    (UInt16* chan);
  219. static void MatchOne_Gray_XYZ    (UInt16* chan);
  220. static void MatchOne_CMYK_LAB    (UInt16* chan);
  221. static void MatchOne_LAB_CMYK    (UInt16* chan);
  222. static void MatchOne_CMYK_XYZ    (UInt16* chan);
  223. static void MatchOne_XYZ_CMYK    (UInt16* chan);
  224. static void MatchOne_RGB_Gray    (UInt16* chan);
  225. static void MatchOne_Gray_RGB    (UInt16* chan);
  226. static void MatchOne_LAB_Gray    (UInt16* chan);
  227. static void MatchOne_Gray_LAB    (UInt16* chan);
  228. static void MatchOne_CMYK_Gray    (UInt16* chan);
  229. static void MatchOne_Gray_CMYK    (UInt16* chan);
  230.  
  231.  
  232. #if TARGET_OS_MAC
  233. // RoutineDescriptors
  234. #if TARGET_CPU_PPC
  235.     // RoutineDescriptors for Component functions
  236.     INSTANTIATE_RD(DoComponentOpen);
  237.     INSTANTIATE_RD(DoComponentClose);
  238.     INSTANTIATE_RD(DoComponentCanDo);
  239.     INSTANTIATE_RD(DoComponentVersion);
  240.     INSTANTIATE_RD(DoComponentRegister);
  241.     INSTANTIATE_RD(DoCMMInit);
  242.     INSTANTIATE_RD(DoNCMMInit);
  243.     INSTANTIATE_RD(DoCMMConcatInit);
  244.     INSTANTIATE_RD(DoNCMMConcatInit);
  245.     INSTANTIATE_RD(DoCMMMatchColors);
  246.     INSTANTIATE_RD(DoCMMCheckColors);
  247.     INSTANTIATE_RD(DoCMMMatchBitmap);
  248.     INSTANTIATE_RD(DoCMMCheckBitmap);
  249.  
  250.     // PowerPC main Component entry point
  251.     RoutineDescriptor mainRD = BUILD_ROUTINE_DESCRIPTOR(uppComponentRoutineProcInfo, main);
  252. //    ProcInfoType __procinfo = uppComponentRoutineProcInfo;
  253. #endif
  254.  
  255.  
  256. #if TARGET_CPU_68K
  257. #pragma code68020 off                        // this functions must run on all Macs
  258. #endif
  259.  
  260. #pragma mark -
  261. #pragma mark ————— Mac component entry point —————
  262.  
  263.  
  264. /* ______________________________________________________________________
  265.  
  266.     ComponentResult
  267.  
  268.     Abstract:
  269.         main entry point to CMM Component
  270.  
  271.     Params:
  272.         params        (in)    Parameters in form used by Component Manager
  273.         storage        (in)    Handle to memory to be used by CMM
  274.         
  275.     Return:
  276.         noErr        If successful
  277.                     Otherwise System or ColorSync result code
  278.  
  279.    _____________________________________________________________________ */
  280.  
  281.  
  282. pascal ComponentResult
  283. main (ComponentParameters *params, Handle storage)
  284. {
  285.     ComponentResult        result = noErr;        /* Init for error handling */
  286.     short                message;        
  287.  
  288.     message = (*params).what;
  289.  
  290.     /* Selectors < 0 for Component Manager functions */ 
  291.     if (message < 0)
  292.     {
  293.         switch (message)
  294.         {
  295.             case kComponentOpenSelect :
  296.             result = CCF(params, DoComponentOpen);
  297.             break;
  298.             
  299.             case kComponentCloseSelect :
  300.             result = CCFWS(storage, params, DoComponentClose);
  301.             break;
  302.             
  303.             case kComponentCanDoSelect :
  304.             result = CCF(params, DoComponentCanDo);
  305.             break;
  306.             
  307.             case kComponentVersionSelect :
  308.             result = CCF(params, DoComponentVersion);
  309.             break;
  310.             
  311.             case kComponentRegisterSelect :
  312.             result = CCF(params, DoComponentRegister);
  313.             break;
  314.             
  315.             default :
  316.             result = noErr;
  317.             break;
  318.         }
  319.     }
  320.     else /* Selectors >= 0 for CMM functions */ 
  321.     {
  322.         switch (message)
  323.         {
  324.              case kCMMInit :
  325.             result = CCFWS(storage, params, DoCMMInit);
  326.             break;
  327.             
  328.              case kNCMMInit :
  329.             result = CCFWS(storage, params, DoNCMMInit);
  330.             break;
  331.             
  332.              case kCMMMatchColors :
  333.             result = CCFWS(storage, params, DoCMMMatchColors);
  334.             break;
  335.             
  336.              case kCMMCheckColors :
  337.             result = CCFWS(storage, params, DoCMMCheckColors);
  338.             break;
  339.             
  340.              case kCMMConcatInit :
  341.             result = CCFWS(storage, params, DoCMMConcatInit);
  342.             break;
  343.             
  344.              case kCMMMatchBitmap :
  345.             result = CCFWS(storage, params, DoCMMMatchBitmap);
  346.             break;
  347.             
  348.              case kCMMCheckBitmap :
  349.             result = CCFWS(storage, params, DoCMMCheckBitmap);
  350.             break;
  351.             
  352.              case kNCMMConcatInit :
  353.             result = CCFWS(storage, params, DoNCMMConcatInit);
  354.             break;
  355.             
  356.             default :
  357.             result = unimpErr;
  358.             break;
  359.         }
  360.     }
  361.     return result ;
  362. }
  363.  
  364.  
  365. static pascal ComponentResult
  366. DoComponentOpen (ComponentInstance self)
  367. {
  368.     ComponentResult        result = noErr;        /* Init for error handling */
  369.     CMMStorageHdl        h;
  370.     
  371.     h = (CMMStorageHdl) NewHandleClear(sizeof(CMMStorageRec));
  372.     if (h == nil)
  373.         result = MemError();
  374.     
  375.     if (result == noErr)
  376.     {
  377.         (**h).ci = self;
  378.         SetComponentInstanceStorage(self, (Handle) h);
  379.     }
  380.     
  381.     return result ;
  382. }
  383.  
  384.  
  385. static pascal ComponentResult
  386. DoComponentClose(CMMStorageHdl storage, ComponentInstance self)
  387. {
  388.     ComponentResult        result = noErr;        /* Init for error handling */
  389.     
  390.     if (storage != nil)
  391.         DisposeHandle((Handle)storage);
  392.     
  393.     return result ;
  394. }
  395.  
  396. static pascal ComponentResult
  397. DoComponentRegister(void)
  398. {
  399.     ComponentResult        result = noErr;        /* Init for error handling */
  400.     long                gestaltCPU;
  401.     long                gestaltSys;
  402.     long                gestaltQD;
  403.     
  404.     // Default -- don't register
  405.     result    = 1;
  406.     
  407.     // We require 68020 processor and 32-Bit Color QD 1.2
  408.     // gestalt68020 is returned for gestaltProcessorType on PowerPC
  409.     if ((Gestalt(gestaltProcessorType, &gestaltCPU) == noErr)    && (gestaltCPU >= gestalt68020)        &&
  410.         (Gestalt(gestaltSystemVersion, &gestaltSys) == noErr)    && (gestaltSys >= 0x0700)            &&
  411.         (Gestalt(gestaltQuickdrawVersion, &gestaltQD) == noErr)    && (gestaltQD >= gestalt32BitQD12))
  412.     {
  413.         // OK to register
  414.         result = 0;
  415.     }
  416.     
  417.     return result ;
  418. }
  419.  
  420.  
  421. #if TARGET_CPU_68K
  422. #pragma code68020 reset
  423. #endif
  424.  
  425.  
  426. static pascal ComponentResult
  427. DoComponentCanDo(short selector)
  428. {
  429.     ComponentResult        result = noErr;        /* Init for error handling */
  430.  
  431.     switch (selector)
  432.     {
  433.         /* Component Manager functions */
  434.         case kComponentOpenSelect:                // -1
  435.         case kComponentCloseSelect:                // -2
  436.         case kComponentCanDoSelect:                // -3
  437.         case kComponentVersionSelect:            // -4
  438.         case kComponentRegisterSelect:            // -5
  439.         result = true;
  440.         break;
  441.         
  442.         /* Supported CMM functions */
  443.         case kCMMInit:                            // 0
  444.         case kNCMMInit:                            // 6
  445.         case kCMMMatchColors:                    // 1
  446.         case kCMMCheckColors:                    // 2
  447.         case kCMMConcatInit:                    // 7
  448.         case kNCMMConcatInit:                    // 18
  449.         result = true;
  450.         break;
  451.  
  452.         case kCMMMatchBitmap:                    // 9
  453.         case kCMMCheckBitmap:                    // 10
  454.         result = true;
  455. //        result = false;
  456.         break;
  457.  
  458.         /* Unsupported CMM functions */
  459.         case kCMMMatchPixMap:                    // 3
  460.         case kCMMCheckPixMap:                    // 4
  461.         case kCMMConcatenateProfiles:            // 5
  462.         case kCMMValidateProfile:                // 8
  463.         case kCMMGetPS2ColorSpace:                // 11
  464.         case kCMMGetPS2ColorRenderingIntent:    // 12
  465.         case kCMMGetPS2ColorRendering:            // 13
  466.         case kCMMFlattenProfile:                // 14
  467.         case kCMMUnflattenProfile:                // 15
  468.         case kCMMNewLinkProfile:                // 16
  469.         case kCMMGetPS2ColorRenderingVMSize:    // 17
  470.         case kNCMMNewLinkProfile:                // 19
  471.         
  472.         result = false;
  473.         break; 
  474.             
  475.         default:
  476.         result = false;
  477.         break; 
  478.     }
  479.  
  480.     return result ;
  481. }
  482.  
  483.  
  484. static pascal ComponentResult
  485. DoComponentVersion(void)
  486. {
  487.     return kCMMVersion;
  488. }
  489.  
  490. #endif
  491.  
  492.  
  493. #if TARGET_OS_WIN32
  494. #pragma mark -
  495. #pragma mark ————— Win entry points —————
  496.  
  497.  
  498.  
  499. CMM_ENTRY CMError
  500. CMMOpen ( UInt32 *cmmRefcon,
  501.           void* hInstance) 
  502. #pragma unused (hInstance)
  503.     *cmmRefcon = (UInt32)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CMMStorageRec));
  504.     if (*cmmRefcon)
  505.         return noErr;
  506.     else
  507.         return memFullErr;
  508. }
  509.  
  510. CMM_ENTRY CMError
  511. CMMClose ( UInt32 *cmmRefcon ) 
  512. {
  513.     if (*cmmRefcon)
  514.         HeapFree(  GetProcessHeap(),  0, (void*)*cmmRefcon);
  515.     return noErr;
  516. }
  517.  
  518.  
  519. CMM_ENTRY CMError  
  520. CMMGetCMMInfo ( UInt32 *cmmRefcon,
  521.                    CMMInfo *info ) 
  522. {
  523. #pragma unused (cmmRefcon)
  524.     CMMInfo theInfo = {
  525.                         sizeof(CMMInfo),
  526.                         FOUR_CHAR_CODE('demo'),
  527.                         FOUR_CHAR_CODE('appl'),
  528.                         kCMMVersion,
  529.                         "Demo CMM",
  530.                         "Demo CMM description string"
  531.                         //,0,"",0,"" 
  532.                         };
  533.     *info = theInfo;
  534.     return noErr;
  535. }
  536.  
  537. CMM_ENTRY CMError  
  538. NCMMInit (UInt32 *cmmRefcon, CMProfileRef srcProfile, CMProfileRef dstProfile)
  539. {
  540.     return DoNCMMInit ((CMMStorageHdl)cmmRefcon, srcProfile, dstProfile);
  541. }
  542.  
  543. CMM_ENTRY CMError  
  544. CMMConcatInit (UInt32 *cmmRefcon, CMConcatProfileSet* profileSet)
  545. {
  546.     return DoCMMConcatInit ((CMMStorageHdl)cmmRefcon, profileSet);
  547. }
  548.  
  549. CMM_ENTRY CMError  
  550. NCMMConcatInit (UInt32 *cmmRefcon, NCMConcatProfileSet* profileSet, CMConcatCallBackUPP proc, void* refCon)
  551. {
  552.     return DoNCMMConcatInit ((CMMStorageHdl)cmmRefcon, profileSet, proc, refCon);
  553. }
  554.  
  555. CMM_ENTRY CMError  
  556. CMMMatchColors (UInt32 *cmmRefcon, CMColor *colorBuf, UInt32 count)
  557. {
  558.     return DoCMMMatchColors ((CMMStorageHdl)cmmRefcon, colorBuf, count);
  559. }
  560.                             
  561. CMM_ENTRY CMError  
  562. CMMCheckColors (UInt32 *cmmRefcon, CMColor *colorBuf, UInt32 count, UInt32* gamutResult)
  563. {
  564.     return DoCMMCheckColors ((CMMStorageHdl)cmmRefcon, colorBuf, count, gamutResult);
  565. }
  566.  
  567. CMM_ENTRY CMError  
  568. CMMMatchBitmap (UInt32 *cmmRefcon, CMBitmap * srcMap,
  569.                  CMBitmapCallBackUPP progressProc, void * refCon,
  570.                  CMBitmap* dstMap)
  571. {
  572.     return DoCMMMatchBitmap ((CMMStorageHdl)cmmRefcon, srcMap, progressProc, refCon, dstMap);
  573. }
  574.  
  575. CMM_ENTRY CMError  
  576. CMMCheckBitmap (UInt32 *cmmRefcon,  const CMBitmap * srcMap,
  577.                  CMBitmapCallBackUPP progressProc, void * refCon,
  578.                  CMBitmap* chkMap)
  579. {
  580.     return DoCMMCheckBitmap ((CMMStorageHdl)cmmRefcon,  srcMap, progressProc, refCon, chkMap);
  581. }
  582.  
  583. #endif
  584.  
  585.  
  586. #pragma mark -
  587. #pragma mark ————— implimentations —————
  588.  
  589.  
  590. static pascal CMError
  591. DoCMMInit(CMMStorageHdl storage, CMProfileHandle srcProfile, CMProfileHandle dstProfile)
  592. {    
  593.     // Check params
  594.     if ((srcProfile == nil) || (dstProfile == nil))
  595.         return paramErr;
  596.     
  597.     (**storage).srcSpace = (**srcProfile).header.dataType;
  598.     (**storage).srcClass = (**srcProfile).header.deviceType;
  599.     
  600.     (**storage).dstSpace = (**dstProfile).header.dataType;
  601.     (**storage).dstClass = (**dstProfile).header.deviceType;
  602.  
  603.     return CheckStorage(storage);
  604. }
  605.                                 
  606.  
  607. typedef struct CMConcatProfileSet2 {
  608.     unsigned short         keyIndex;        /* Zero-based */
  609.     unsigned short         count;            /* Min 1, Max 2 */
  610.     CMProfileRef         profileSet[2];    /* Fixed. Source and Dest */
  611. } CMConcatProfileSet2;
  612.  
  613. static pascal CMError
  614. DoNCMMInit (CMMStorageHdl storage, CMProfileRef srcProfile, CMProfileRef dstProfile)
  615. {
  616.     CMConcatProfileSet2        set;
  617.     
  618.     set.keyIndex = 0;
  619.     set.count = 2;
  620.     set.profileSet[0] = srcProfile;
  621.     set.profileSet[1] = dstProfile;
  622.         
  623.     return DoCMMConcatInit(storage, (CMConcatProfileSet*)&set);
  624. }
  625.  
  626.  
  627. static pascal CMError
  628. DoCMMConcatInit (CMMStorageHdl storage, CMConcatProfileSet* profileSet)
  629. {
  630.     ComponentResult            result = noErr;        /* Init for error handling */
  631.     CMAppleProfileHeader    srcHdr;
  632.     CMAppleProfileHeader    dstHdr;
  633.     CMProfileRef            srcProfile;
  634.     CMProfileRef            dstProfile;
  635.     
  636.     // Check params
  637.     if (profileSet==nil)
  638.         return paramErr;
  639.     
  640.     srcProfile = profileSet->profileSet[0];
  641.     dstProfile = profileSet->profileSet[profileSet->count-1];
  642.     if ((srcProfile == nil) || (dstProfile == nil))
  643.         return paramErr;
  644.     
  645.     if (result == noErr)
  646.         result = CMGetProfileHeader(srcProfile, &srcHdr);
  647.     
  648.     if (result == noErr)
  649.         result = CMGetProfileHeader(dstProfile, &dstHdr);
  650.     
  651.     if (result == noErr)
  652.     {
  653.         (**storage).srcSpace = srcHdr.cm2.dataColorSpace;
  654.         (**storage).srcClass = srcHdr.cm2.profileClass;
  655.         
  656.         (**storage).dstSpace = dstHdr.cm2.dataColorSpace;
  657.         (**storage).dstClass = dstHdr.cm2.profileClass;
  658.         
  659.         result = CheckStorage(storage);
  660.     }
  661.         
  662.     return result ;
  663. }
  664.  
  665.  
  666.  
  667. static pascal CMError
  668. DoNCMMConcatInit (CMMStorageHdl storage, NCMConcatProfileSet* profileSet, CMConcatCallBackUPP, void*)
  669. {
  670.     ComponentResult            result = noErr;        /* Init for error handling */
  671.     CMAppleProfileHeader    srcHdr;
  672.     CMAppleProfileHeader    dstHdr;
  673.     CMProfileRef            srcProfile;
  674.     CMProfileRef            dstProfile;
  675.     UInt32                     srcTransform;
  676.     UInt32                     dstTransform;
  677.     
  678.     // Check params
  679.     if (profileSet==nil)
  680.         return paramErr;
  681.     
  682.     srcProfile = profileSet->profileSpecs[0].profile;
  683.     dstProfile = profileSet->profileSpecs[profileSet->profileCount-1].profile;
  684.     if ((srcProfile == nil) || (dstProfile == nil))
  685.         return paramErr;
  686.     
  687.     srcTransform = profileSet->profileSpecs[0].transformTag;
  688.     dstTransform = profileSet->profileSpecs[profileSet->profileCount-1].transformTag;
  689.     
  690.     if (result == noErr)
  691.         result = CMGetProfileHeader(srcProfile, &srcHdr);
  692.     
  693.     if (result == noErr)
  694.         result = CMGetProfileHeader(dstProfile, &dstHdr);
  695.     
  696.     if (result == noErr)
  697.     {
  698.         (**storage).srcSpace = srcHdr.cm2.dataColorSpace;
  699.         (**storage).srcClass = srcHdr.cm2.profileClass;
  700.         
  701.         (**storage).dstSpace = dstHdr.cm2.dataColorSpace;
  702.         (**storage).dstClass = dstHdr.cm2.profileClass;
  703.         
  704.         result = CheckStorage(storage);
  705.     }
  706.         
  707.     return result ;
  708. }
  709.  
  710.  
  711.  
  712. static pascal CMError
  713. DoCMMMatchColors (CMMStorageHdl storage, CMColor *colorBuf, UInt32 count)
  714. {
  715.     CMMMatchRec            matchInfo;
  716.     
  717.     matchInfo.storage        = storage;
  718.     matchInfo.height        = count;
  719.     matchInfo.width            = 1;
  720.     matchInfo.srcSpace        = (**storage).srcSpace;
  721.     matchInfo.srcBuf[0]        = ((UInt8*)colorBuf) + 0;
  722.     matchInfo.srcBuf[1]        = ((UInt8*)colorBuf) + 2;
  723.     matchInfo.srcBuf[2]        = ((UInt8*)colorBuf) + 4;
  724.     matchInfo.srcBuf[3]        = ((UInt8*)colorBuf) + 6;
  725.     matchInfo.srcChanBits    = 16;
  726.     matchInfo.srcRowBytes    = sizeof(CMColor);
  727.     matchInfo.srcColBytes    = sizeof(CMColor);
  728.     matchInfo.srcSwap        = false;
  729.     
  730.     matchInfo.dstSpace        = (**storage).dstSpace;
  731.     matchInfo.dstBuf[0]        = ((UInt8*)colorBuf) + 0;
  732.     matchInfo.dstBuf[1]        = ((UInt8*)colorBuf) + 2;
  733.     matchInfo.dstBuf[2]        = ((UInt8*)colorBuf) + 4;
  734.     matchInfo.dstBuf[3]        = ((UInt8*)colorBuf) + 6;
  735.     matchInfo.dstChanBits    = 16;
  736.     matchInfo.dstRowBytes    = sizeof(CMColor);
  737.     matchInfo.dstColBytes    = sizeof(CMColor);
  738.     matchInfo.dstSwap        = false;
  739.     
  740.     MatchAll(&matchInfo);
  741.     
  742.     return noErr;
  743. }
  744.                                 
  745.  
  746. static pascal CMError
  747. DoCMMCheckColors (CMMStorageHdl storage,  CMColor *colorBuf, UInt32 count, UInt32* gamutResult)
  748. {
  749. #pragma unused (storage, colorBuf)
  750.     
  751.     UInt32        longCount;
  752.     
  753.     /* Everything is in gamut. This is just sample code. */
  754.     
  755.     longCount = (count + 31) / 32;
  756.     
  757.     while (longCount--)
  758.         *gamutResult++ = 0xFFFFFFFF;
  759.     
  760.     return noErr;
  761. }
  762.  
  763.  
  764. static pascal CMError
  765. DoCMMMatchBitmap (CMMStorageHdl storage,  const CMBitmap * srcMap,
  766.                  CMBitmapCallBackUPP progressProc, void * refCon,
  767.                  CMBitmap* dstMap)
  768. {
  769. #pragma unused (progressProc, refCon)
  770.     
  771.     CMMMatchRec            matchInfo;
  772.     
  773.     // Check params
  774.     if (srcMap==nil || dstMap==nil)
  775.         return paramErr;
  776.     
  777.     matchInfo.storage        = storage;
  778.     matchInfo.height        = srcMap->height;
  779.     matchInfo.width            = srcMap->width;
  780.     matchInfo.srcRowBytes    = srcMap->rowBytes;
  781.     matchInfo.dstRowBytes    = dstMap->rowBytes;
  782.     
  783.     switch (srcMap->space)
  784.     {
  785.         case cmGray8Space:
  786.         matchInfo.srcSpace        = cmGrayData;
  787.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  788.         matchInfo.srcBuf[1]        = nil;
  789.         matchInfo.srcBuf[2]        = nil;
  790.         matchInfo.srcBuf[3]        = nil;
  791.         matchInfo.srcChanBits    = 8;
  792.         matchInfo.srcColBytes    = 1;
  793.         break;
  794.         
  795.         case cmGray16Space:
  796.         case cmGray16LSpace:
  797.         matchInfo.srcSpace        = cmGrayData;
  798.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  799.         matchInfo.srcBuf[1]        = nil;
  800.         matchInfo.srcBuf[2]        = nil;
  801.         matchInfo.srcBuf[3]        = nil;
  802.         matchInfo.srcChanBits    = 16;
  803.         matchInfo.srcColBytes    = 2;
  804.         break;
  805.     
  806.         case cmRGB24Space:
  807.         matchInfo.srcSpace        = cmRGBData;
  808.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  809.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 1;
  810.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 2;
  811.         matchInfo.srcBuf[3]        = nil;
  812.         matchInfo.srcChanBits    = 8;
  813.         matchInfo.srcColBytes    = 3;
  814.         break;
  815.         
  816.         case cmRGB32Space:
  817.         matchInfo.srcSpace        = cmRGBData;
  818.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 1;
  819.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 2;
  820.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 3;
  821.         matchInfo.srcBuf[3]        = nil;
  822.         matchInfo.srcChanBits    = 8;
  823.         matchInfo.srcColBytes    = 4;
  824.         break;
  825.         
  826.         case cmRGB48Space:
  827.         case cmRGB48LSpace:
  828.         matchInfo.srcSpace        = cmRGBData;
  829.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  830.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 2;
  831.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 4;
  832.         matchInfo.srcBuf[3]        = nil;
  833.         matchInfo.srcChanBits    = 16;
  834.         matchInfo.srcColBytes    = 6;
  835.         break;
  836.         
  837.         case cmCMYK32Space:
  838.         matchInfo.srcSpace        = cmCMYKData;
  839.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  840.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 1;
  841.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 2;
  842.         matchInfo.srcBuf[3]        = (UInt8*)srcMap->image + 3;
  843.         matchInfo.srcChanBits    = 8;
  844.         matchInfo.srcColBytes    = 4;
  845.         break;
  846.         
  847.         case cmCMYK64Space:
  848.         case cmCMYK64LSpace:
  849.         matchInfo.srcSpace        = cmCMYKData;
  850.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  851.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 2;
  852.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 4;
  853.         matchInfo.srcBuf[3]        = (UInt8*)srcMap->image + 6;
  854.         matchInfo.srcChanBits    = 16;
  855.         matchInfo.srcColBytes    = 8;
  856.         break;
  857.         
  858.         case cmLAB24Space:
  859.         matchInfo.srcSpace        = cmLabData;
  860.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  861.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 1;
  862.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 2;
  863.         matchInfo.srcBuf[3]        = nil;
  864.         matchInfo.srcChanBits    = 8;
  865.         matchInfo.srcColBytes    = 3;
  866.         break;
  867.         
  868.         case cmLAB48Space:
  869.         case cmLAB48LSpace:
  870.         matchInfo.srcSpace        = cmLabData;
  871.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  872.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 2;
  873.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 4;
  874.         matchInfo.srcBuf[3]        = nil;
  875.         matchInfo.srcChanBits    = 16;
  876.         matchInfo.srcColBytes    = 6;
  877.         break;
  878.         
  879.         case cmXYZ24Space:
  880.         matchInfo.srcSpace        = cmXYZData;
  881.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  882.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 1;
  883.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 2;
  884.         matchInfo.srcBuf[3]        = nil;
  885.         matchInfo.srcChanBits    = 8;
  886.         matchInfo.srcColBytes    = 3;
  887.         break;
  888.         
  889.         case cmXYZ48Space:
  890.         case cmXYZ48LSpace:
  891.         matchInfo.srcSpace        = cmXYZData;
  892.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  893.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 2;
  894.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 4;
  895.         matchInfo.srcBuf[3]        = nil;
  896.         matchInfo.srcChanBits    = 16;
  897.         matchInfo.srcColBytes    = 6;
  898.         break;
  899.         
  900.         default:
  901.         return cmInvalidSrcMap;
  902.         break;
  903.     }
  904.     
  905.     #if TARGET_RT_LITTLE_ENDIAN
  906.         matchInfo.srcSwap = ((srcMap->space & cmLittleEndianPacking) == 0);
  907.     #else
  908.         matchInfo.srcSwap = ((srcMap->space & cmLittleEndianPacking) == cmLittleEndianPacking);
  909.     #endif
  910.     
  911.     
  912.     switch (dstMap->space)
  913.     {
  914.         case cmGray8Space:
  915.         matchInfo.dstSpace        = cmGrayData;
  916.         matchInfo.dstBuf[0]        = (UInt8*)srcMap->image + 0;
  917.         matchInfo.dstBuf[1]        = nil;
  918.         matchInfo.dstBuf[2]        = nil;
  919.         matchInfo.dstBuf[3]        = nil;
  920.         matchInfo.dstChanBits    = 8;
  921.         matchInfo.dstColBytes    = 1;
  922.         break;
  923.         
  924.         case cmGray16Space:
  925.         case cmGray16LSpace:
  926.         matchInfo.dstSpace        = cmGrayData;
  927.         matchInfo.dstBuf[0]        = (UInt8*)srcMap->image + 0;
  928.         matchInfo.dstBuf[1]        = nil;
  929.         matchInfo.dstBuf[2]        = nil;
  930.         matchInfo.dstBuf[3]        = nil;
  931.         matchInfo.dstChanBits    = 16;
  932.         matchInfo.dstColBytes    = 2;
  933.         break;
  934.     
  935.         case cmRGB24Space:
  936.         matchInfo.dstSpace        = cmRGBData;
  937.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 0;
  938.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 1;
  939.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 2;
  940.         matchInfo.dstBuf[3]        = nil;
  941.         matchInfo.dstChanBits    = 8;
  942.         matchInfo.dstColBytes    = 3;
  943.         break;
  944.         
  945.         case cmRGB32Space:
  946.         matchInfo.dstSpace        = cmRGBData;
  947.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 1;
  948.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 2;
  949.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 3;
  950.         matchInfo.dstBuf[3]        = nil;
  951.         matchInfo.dstChanBits    = 8;
  952.         matchInfo.dstColBytes    = 4;
  953.         break;
  954.         
  955.         case cmRGB48Space:
  956.         case cmRGB48LSpace:
  957.         matchInfo.dstSpace        = cmRGBData;
  958.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 0;
  959.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 2;
  960.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 4;
  961.         matchInfo.dstBuf[3]        = nil;
  962.         matchInfo.dstChanBits    = 16;
  963.         matchInfo.dstColBytes    = 6;
  964.         break;
  965.         
  966.         case cmCMYK32Space:
  967.         matchInfo.dstSpace        = cmCMYKData;
  968.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 0;
  969.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 1;
  970.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 2;
  971.         matchInfo.dstBuf[3]        = (UInt8*)dstMap->image + 3;
  972.         matchInfo.dstChanBits    = 8;
  973.         matchInfo.dstColBytes    = 4;
  974.         break;
  975.         
  976.         case cmCMYK64Space:
  977.         case cmCMYK64LSpace:
  978.         matchInfo.dstSpace        = cmCMYKData;
  979.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 0;
  980.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 2;
  981.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 4;
  982.         matchInfo.dstBuf[3]        = (UInt8*)dstMap->image + 6;
  983.         matchInfo.dstChanBits    = 16;
  984.         matchInfo.dstColBytes    = 8;
  985.         break;
  986.         
  987.         case cmLAB24Space:
  988.         matchInfo.dstSpace        = cmLabData;
  989.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 0;
  990.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 1;
  991.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 2;
  992.         matchInfo.dstBuf[3]        = nil;
  993.         matchInfo.dstChanBits    = 8;
  994.         matchInfo.dstColBytes    = 3;
  995.         break;
  996.         
  997.         case cmLAB48Space:
  998.         case cmLAB48LSpace:
  999.         matchInfo.dstSpace        = cmLabData;
  1000.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 0;
  1001.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 2;
  1002.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 4;
  1003.         matchInfo.dstBuf[3]        = nil;
  1004.         matchInfo.dstChanBits    = 16;
  1005.         matchInfo.dstColBytes    = 6;
  1006.         break;
  1007.         
  1008.         case cmXYZ24Space:
  1009.         matchInfo.dstSpace        = cmXYZData;
  1010.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 0;
  1011.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 1;
  1012.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 2;
  1013.         matchInfo.dstBuf[3]        = nil;
  1014.         matchInfo.dstChanBits    = 8;
  1015.         matchInfo.dstColBytes    = 3;
  1016.         break;
  1017.         
  1018.         case cmXYZ48Space:
  1019.         case cmXYZ48LSpace:
  1020.         matchInfo.dstSpace        = cmXYZData;
  1021.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 0;
  1022.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 2;
  1023.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 4;
  1024.         matchInfo.dstBuf[3]        = nil;
  1025.         matchInfo.dstChanBits    = 16;
  1026.         matchInfo.dstColBytes    = 6;
  1027.         break;
  1028.         
  1029.         default:
  1030.         return cmInvalidSrcMap;
  1031.         break;
  1032.     }
  1033.     
  1034.     #if TARGET_RT_LITTLE_ENDIAN
  1035.         matchInfo.dstSwap = ((dstMap->space & cmLittleEndianPacking) == 0);
  1036.     #else
  1037.         matchInfo.dstSwap = ((dstMap->space & cmLittleEndianPacking) == cmLittleEndianPacking);
  1038.     #endif
  1039.     
  1040.     
  1041.     if ((**storage).srcSpace != matchInfo.srcSpace)
  1042.         return cmInvalidSrcMap;
  1043.     
  1044.     
  1045.     if ((**storage).dstSpace != matchInfo.dstSpace)
  1046.         return cmInvalidDstMap;
  1047.     
  1048.     MatchAll(&matchInfo);
  1049.     
  1050.     return noErr;
  1051. }
  1052.  
  1053.  
  1054. static pascal CMError
  1055. DoCMMCheckBitmap (CMMStorageHdl storage,  const CMBitmap * srcMap,
  1056.                  CMBitmapCallBackUPP progressProc, void * refCon,
  1057.                  CMBitmap* chkMap)
  1058. {
  1059. #pragma unused (storage, srcMap, progressProc, refCon, chkMap)
  1060.     return paramErr;
  1061. }
  1062.  
  1063.  
  1064. #pragma mark -
  1065. #pragma mark ————— utilities —————
  1066.  
  1067. static CMError
  1068. CheckStorage (CMMStorageHdl storage)
  1069. {
  1070.     OSType            srcSpace = (**storage).srcSpace;
  1071.     OSType            dstSpace = (**storage).dstSpace;
  1072.     
  1073.     (**storage).proc = nil;
  1074.     
  1075.     if (srcSpace == dstSpace)
  1076.         return noErr;
  1077.     
  1078.     if      (srcSpace==cmRGBData  && dstSpace==cmCMYKData)        (**storage).proc = &MatchOne_RGB_CMYK;
  1079.     else if (srcSpace==cmRGBData  && dstSpace==cmXYZData)        (**storage).proc = &MatchOne_RGB_XYZ;
  1080.     else if (srcSpace==cmRGBData  && dstSpace==cmLabData)        (**storage).proc = &MatchOne_RGB_LAB;
  1081.     else if (srcSpace==cmRGBData  && dstSpace==cmGrayData)        (**storage).proc = &MatchOne_RGB_Gray;
  1082.     else if (srcSpace==cmCMYKData && dstSpace==cmRGBData)        (**storage).proc = &MatchOne_CMYK_RGB;
  1083.     else if (srcSpace==cmCMYKData && dstSpace==cmLabData)        (**storage).proc = &MatchOne_CMYK_LAB;
  1084.     else if (srcSpace==cmCMYKData && dstSpace==cmXYZData)        (**storage).proc = &MatchOne_CMYK_XYZ;
  1085.     else if (srcSpace==cmCMYKData && dstSpace==cmGrayData)        (**storage).proc = &MatchOne_CMYK_Gray;
  1086.     else if (srcSpace==cmXYZData  && dstSpace==cmRGBData)        (**storage).proc = &MatchOne_XYZ_RGB;
  1087.     else if (srcSpace==cmXYZData  && dstSpace==cmLabData)        (**storage).proc = &MatchOne_XYZ_LAB;
  1088.     else if (srcSpace==cmXYZData  && dstSpace==cmCMYKData)        (**storage).proc = &MatchOne_XYZ_CMYK;
  1089.     else if (srcSpace==cmXYZData  && dstSpace==cmGrayData)        (**storage).proc = &MatchOne_XYZ_Gray;
  1090.     else if (srcSpace==cmLabData  && dstSpace==cmRGBData)        (**storage).proc = &MatchOne_LAB_RGB;
  1091.     else if (srcSpace==cmLabData  && dstSpace==cmXYZData)        (**storage).proc = &MatchOne_LAB_XYZ;
  1092.     else if (srcSpace==cmLabData  && dstSpace==cmCMYKData)        (**storage).proc = &MatchOne_LAB_CMYK;
  1093.     else if (srcSpace==cmLabData  && dstSpace==cmGrayData)        (**storage).proc = &MatchOne_LAB_Gray;
  1094.     else if (srcSpace==cmGrayData && dstSpace==cmRGBData)        (**storage).proc = &MatchOne_Gray_RGB;
  1095.     else if (srcSpace==cmGrayData && dstSpace==cmCMYKData)        (**storage).proc = &MatchOne_Gray_CMYK;
  1096.     else if (srcSpace==cmGrayData && dstSpace==cmXYZData)        (**storage).proc = &MatchOne_Gray_XYZ;
  1097.     else if (srcSpace==cmGrayData && dstSpace==cmLabData)        (**storage).proc = &MatchOne_Gray_LAB;
  1098.     else
  1099.         return cmInvalidProfile;
  1100.     
  1101.     return noErr;
  1102. }
  1103.  
  1104.  
  1105. static void
  1106. DebugColor4( UInt16* color)
  1107. {
  1108. #if TARGET_OS_MAC
  1109.     Str255            s = "\p 0xXXXX, 0xXXXX, 0xXXXX, 0xXXXX";
  1110.     UInt8*            c = &(s[4]);
  1111. #else if TARGET_OS_WIN32
  1112.     char            s[] = " 0xXXXX, 0xXXXX, 0xXXXX, 0xXXXX";
  1113.     char*            c = &(s[3]);
  1114. #endif
  1115.     int                i;
  1116.     int                v;
  1117.     
  1118.     for (i=0; i<4; i++)
  1119.     {
  1120.         v = (((*color)>>12) & 0x000F);    *c++ = (v<10) ? (v+'0') : (v+'A'-10);
  1121.         v = (((*color)>>8) & 0x000F);    *c++ = (v<10) ? (v+'0') : (v+'A'-10);
  1122.         v = (((*color)>>4) & 0x000F);    *c++ = (v<10) ? (v+'0') : (v+'A'-10);
  1123.         v = (((*color)) & 0x000F);        *c++ = (v<10) ? (v+'0') : (v+'A'-10);
  1124.         c += 4;
  1125.         color++;
  1126.     }
  1127.     
  1128. #if TARGET_OS_MAC
  1129.     DebugStr(s);
  1130. #else if TARGET_OS_WIN32
  1131. #endif
  1132. }
  1133.  
  1134.  
  1135. //
  1136. // Simple conversion of a bunch or colors. This is just sample code.
  1137. //
  1138. static void
  1139. MatchAll (CMMMatchPtr pMatchInfo)
  1140. {
  1141.     UInt32                r,c;
  1142.     UInt16                chan[4];
  1143.     UInt8**                sBuf;
  1144.     UInt8**                dBuf;
  1145.     
  1146.     sBuf = pMatchInfo->srcBuf;
  1147.     dBuf = pMatchInfo->dstBuf;
  1148.     
  1149.     for (r=0; r < pMatchInfo->height; r++)
  1150.     {
  1151.         for (c=0; c < pMatchInfo->width; c++)
  1152.         {
  1153.             // read color in from source buffer
  1154.             if (pMatchInfo->srcChanBits==16)
  1155.             {
  1156.                 if (sBuf[0]) chan[0] = *(UInt16*)(sBuf[0] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  1157.                 if (sBuf[1]) chan[1] = *(UInt16*)(sBuf[1] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  1158.                 if (sBuf[2]) chan[2] = *(UInt16*)(sBuf[2] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  1159.                 if (sBuf[3]) chan[3] = *(UInt16*)(sBuf[3] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  1160.             }
  1161.             else
  1162.             {
  1163.                 if (sBuf[0]) chan[0] = *(UInt8*)(sBuf[0] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  1164.                 if (sBuf[1]) chan[1] = *(UInt8*)(sBuf[1] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  1165.                 if (sBuf[2]) chan[2] = *(UInt8*)(sBuf[2] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  1166.                 if (sBuf[3]) chan[3] = *(UInt8*)(sBuf[3] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  1167.                 chan[0] = (chan[0] << 8) | chan[0];
  1168.                 chan[1] = (chan[1] << 8) | chan[1];
  1169.                 chan[2] = (chan[2] << 8) | chan[2];
  1170.                 chan[3] = (chan[3] << 8) | chan[3];
  1171.             }
  1172.             
  1173.             if (pMatchInfo->srcSwap)
  1174.             {
  1175.                 chan[0] = Endian16_Swap(chan[0]);
  1176.                 chan[1] = Endian16_Swap(chan[1]);
  1177.                 chan[2] = Endian16_Swap(chan[2]);
  1178.                 chan[3] = Endian16_Swap(chan[3]);
  1179.             }
  1180.             
  1181.             // DebugColor4(chan);
  1182.             
  1183.             // Match the color
  1184.             if ((**(pMatchInfo->storage)).proc)
  1185.                 ((**(pMatchInfo->storage)).proc)(chan);
  1186.             
  1187.             // DebugColor4(chan);
  1188.             
  1189.             if (pMatchInfo->dstSwap)
  1190.             {
  1191.                 chan[0] = Endian16_Swap(chan[0]);
  1192.                 chan[1] = Endian16_Swap(chan[1]);
  1193.                 chan[2] = Endian16_Swap(chan[2]);
  1194.                 chan[3] = Endian16_Swap(chan[3]);
  1195.             }
  1196.             
  1197.             // Write color to destination buffer
  1198.             if (pMatchInfo->dstChanBits==16)
  1199.             {
  1200.                 if (dBuf[0]) *(UInt16*)(dBuf[0] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[0];
  1201.                 if (dBuf[1]) *(UInt16*)(dBuf[1] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[1];
  1202.                 if (dBuf[2]) *(UInt16*)(dBuf[2] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[2];
  1203.                 if (dBuf[3]) *(UInt16*)(dBuf[3] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[3];
  1204.             }
  1205.             else
  1206.             {
  1207.                 if (dBuf[0]) *(UInt8*)(dBuf[0] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[0] >> 8;
  1208.                 if (dBuf[1]) *(UInt8*)(dBuf[1] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[1] >> 8;
  1209.                 if (dBuf[2]) *(UInt8*)(dBuf[2] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[2] >> 8;
  1210.                 if (dBuf[3]) *(UInt8*)(dBuf[3] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[3] >> 8;
  1211.             }
  1212.         }
  1213.     }
  1214. }
  1215.  
  1216.  
  1217. //
  1218. // Simple conversions of one color with 16 bits-per-channel 
  1219. //
  1220. static void
  1221. MatchOne_RGB_CMYK (UInt16* chan)
  1222. {
  1223.     chan[0] = 0xFFFF - chan[0];
  1224.     chan[1] = 0xFFFF - chan[1];
  1225.     chan[2] = 0xFFFF - chan[2];
  1226.     chan[3] = (chan[0] < chan[1]) ?
  1227.                 ( (chan[0] < chan[2]) ? (chan[0]) : (chan[2]) ) :
  1228.                 ( (chan[1] < chan[2]) ? (chan[1]) : (chan[2]) );
  1229.     chan[0] -= chan[3];
  1230.     chan[1] -= chan[3];
  1231.     chan[2] -= chan[3];
  1232. }
  1233.  
  1234. static void
  1235. MatchOne_CMYK_RGB (UInt16* chan)
  1236. {
  1237.     chan[0] = 0xFFFF - chan[0];
  1238.     chan[1] = 0xFFFF - chan[1];
  1239.     chan[2] = 0xFFFF - chan[2];
  1240.     chan[0] = (chan[0] > chan[3]) ? (chan[0] - chan[3]) : 0;
  1241.     chan[1] = (chan[1] > chan[3]) ? (chan[1] - chan[3]) : 0;
  1242.     chan[2] = (chan[2] > chan[3]) ? (chan[2] - chan[3]) : 0;
  1243.     chan[3] = 0;
  1244. }
  1245.  
  1246. #define DoubToUInt16(x)        (((x)<=0.0)?(0):(((x)>=1.0)?(65535):((x)*65535.0 + 0.5)))
  1247. #define UInt16ToDoub(x)        ((double)(x)/65535.0)
  1248. #define DoubToFract(x)        (((x)<=0.0)?(0):(((x)>=2.0)?(65535):((x)*32768.0 + 0.5)))
  1249. #define FractToDoub(x)        ((double)(x)/32768.0)
  1250. #define UInt16ToFract(x)    ((x)>>1)
  1251. #define FractToUInt16(x)    ((x)<<1)
  1252.  
  1253. static void
  1254. MatchOne_RGB_XYZ (UInt16* chan)
  1255. {
  1256.     double r,g,b;
  1257.     double X,Y,Z;
  1258.     
  1259.     r = UInt16ToDoub(chan[0]);
  1260.     g = UInt16ToDoub(chan[1]);
  1261.     b = UInt16ToDoub(chan[2]);
  1262.     
  1263.     X = (0.418 * r) + (0.363 * g) + (0.183 * b);
  1264.     Y = (0.213 * r) + (0.715 * g) + (0.072 * b);
  1265.     Z = (0.015 * r) + (0.090 * g) + (0.720 * b);
  1266.      
  1267.     chan[0] = DoubToFract(X);
  1268.     chan[1] = DoubToFract(Y);
  1269.     chan[2] = DoubToFract(Z);
  1270. }
  1271.  
  1272. static void
  1273. MatchOne_XYZ_RGB (UInt16* chan)
  1274. {
  1275.     double r,g,b;
  1276.     double X,Y,Z;
  1277.     
  1278.     X = FractToDoub(chan[0]);
  1279.     Y = FractToDoub(chan[1]);
  1280.     Z = FractToDoub(chan[2]);
  1281.     
  1282.     r = ( 3.202 * X) + (-1.543 * Y) + (-0.660 * Z);
  1283.     g = (-0.959 * X) + ( 1.879 * Y) + ( 0.056 * Z);
  1284.     b = ( 0.053 * X) + (-0.203 * Y) + ( 1.396 * Z);
  1285.     
  1286.     chan[0] = DoubToUInt16(r);
  1287.     chan[1] = DoubToUInt16(g);
  1288.     chan[2] = DoubToUInt16(b);
  1289. }
  1290.  
  1291. static void
  1292. MatchOne_RGB_LAB (UInt16* chan)
  1293. {
  1294.     MatchOne_RGB_XYZ(chan);
  1295.     MatchOne_XYZ_LAB(chan);
  1296. }
  1297.  
  1298. static void
  1299. MatchOne_LAB_RGB (UInt16* chan)
  1300. {
  1301.     MatchOne_LAB_XYZ(chan);
  1302.     MatchOne_XYZ_RGB(chan);
  1303. }
  1304.  
  1305. static void
  1306. MatchOne_XYZ_LAB (UInt16* chan)
  1307. {
  1308. #if TARGET_CPU_68K
  1309.     CMXYZColor white;
  1310.     white.X = 31594;
  1311.     white.Y = 32768;
  1312.     white.Z = 27030;
  1313.     CMConvertXYZToLab( (CMColor*)chan, &white, (CMColor*)chan,1);
  1314. #else
  1315.     double                X, Y, Z;
  1316.     double                L, a, b;
  1317.     double                fx, fy, fz;
  1318.  
  1319.     X = FractToDoub(chan[0]);
  1320.     Y = FractToDoub(chan[1]);
  1321.     Z = FractToDoub(chan[2]);
  1322.  
  1323.     X /= 0.9642;
  1324.     Z /= 0.8249;
  1325.  
  1326.     if (X > 0.008856)
  1327.         fx = pow(X, 0.3333);
  1328.     else
  1329.         fx = 7.787 * X + 16.0 / 116.0;
  1330.     
  1331.     if (Y > 0.008856)
  1332.         fy = pow(Y, 0.3333);
  1333.     else
  1334.         fy = 7.787 * Y + 16.0 / 116.0;
  1335.     
  1336.     if (Z > 0.008856)
  1337.         fz = pow(Z, 0.3333);
  1338.     else
  1339.         fz = 7.787 * Z + 16.0 / 116.0;
  1340.  
  1341.     L = 116.0 * fy - 16;
  1342.     a = 500.0 * (fx - fy);
  1343.     b = 200.0 * (fy - fz);
  1344.     
  1345.     L = L / 100.0;
  1346.     a = (a + 128.0) / 256.0;
  1347.     b = (b + 128.0) / 256.0;
  1348.     
  1349.     chan[0] = DoubToUInt16(L);
  1350.     chan[1] = DoubToUInt16(a);
  1351.     chan[2] = DoubToUInt16(b);
  1352. #endif
  1353. }
  1354.  
  1355. static void
  1356. MatchOne_LAB_XYZ (UInt16* chan)
  1357. {
  1358. #if TARGET_CPU_68K
  1359.     CMXYZColor white;
  1360.     white.X = 31594;
  1361.     white.Y = 32768;
  1362.     white.Z = 27030;
  1363.     CMConvertLabToXYZ( (CMColor*)chan, &white, (CMColor*)chan,1);
  1364. #else
  1365.     double                X, Y, Z;
  1366.     double                L, a, b;
  1367.     double                fx, fy, fz;
  1368.  
  1369.     L = UInt16ToDoub(chan[0]) * 100.0;
  1370.     a = UInt16ToDoub(chan[1]) * 256.0 - 128.0;
  1371.     b = UInt16ToDoub(chan[2]) * 256.0 - 128.0;
  1372.     
  1373.     fy = (L + 16.0) / 116.0;
  1374.     fx = a / 500.0 + fy;
  1375.     fz = fy - b / 200.0;
  1376.     
  1377.     if (fx > 0.20696) 
  1378.         X = pow(fx, 3);
  1379.     else
  1380.         X = (fx - 16.0 / 116.0) / 7.787;
  1381.     
  1382.     if (fy > 0.20696) 
  1383.         Y = pow(fy, 3);
  1384.     else
  1385.         Y = (fy - 16.0 / 116.0) / 7.787;
  1386.     
  1387.     if (fz > 0.20696) 
  1388.         Z = pow(fz, 3);
  1389.     else
  1390.         Z = (fz - 16.0 / 116.0) / 7.787;
  1391.     
  1392.     X *= 0.9642;
  1393.     Z *= 0.8249;
  1394.  
  1395.     chan[0] = DoubToFract(X);
  1396.     chan[1] = DoubToFract(Y);
  1397.     chan[2] = DoubToFract(Z);
  1398. #endif
  1399. }
  1400.  
  1401. static void
  1402. MatchOne_CMYK_LAB (UInt16* chan)
  1403. {
  1404.     MatchOne_CMYK_RGB(chan);
  1405.     MatchOne_RGB_LAB(chan);
  1406. }
  1407.  
  1408. static void
  1409. MatchOne_LAB_CMYK (UInt16* chan)
  1410. {
  1411.     MatchOne_LAB_RGB(chan);
  1412.     MatchOne_RGB_CMYK(chan);
  1413. }
  1414.  
  1415. static void
  1416. MatchOne_CMYK_XYZ (UInt16* chan)
  1417. {
  1418.     MatchOne_CMYK_RGB(chan);
  1419.     MatchOne_RGB_XYZ(chan);
  1420. }
  1421.  
  1422. static void
  1423. MatchOne_XYZ_CMYK (UInt16* chan)
  1424. {
  1425.     MatchOne_XYZ_RGB(chan);
  1426.     MatchOne_RGB_CMYK(chan);
  1427. }
  1428.  
  1429. static void
  1430. MatchOne_RGB_Gray (UInt16* chan)
  1431. {
  1432.     UInt16 alpha;
  1433.     alpha = chan[3]; // preserve alpha
  1434.     MatchOne_RGB_XYZ(chan);
  1435.     MatchOne_XYZ_Gray(chan);
  1436.     chan[1] = alpha; // preserve alpha
  1437. }
  1438.  
  1439. static void
  1440. MatchOne_Gray_RGB (UInt16* chan)
  1441. {
  1442.     chan[3] = chan[1]; // preserve alpha
  1443.     chan[1] = chan[2] = chan[0];
  1444. }
  1445.  
  1446. static void
  1447. MatchOne_LAB_Gray (UInt16* chan)
  1448. {
  1449. #pragma unused (chan)
  1450.     // nothing to do gray = L
  1451. }
  1452.  
  1453. static void
  1454. MatchOne_Gray_LAB (UInt16* chan)
  1455. {
  1456.     chan[1] = chan[2] = 0;
  1457. }
  1458.  
  1459. static void
  1460. MatchOne_CMYK_Gray (UInt16* chan)
  1461. {
  1462.     MatchOne_CMYK_XYZ(chan);
  1463.     MatchOne_XYZ_Gray(chan);
  1464. }
  1465.  
  1466. static void
  1467. MatchOne_Gray_CMYK (UInt16* chan)
  1468. {
  1469.     chan[3] = chan[0]; // K = gray
  1470.     chan[0] = chan[1] = chan[2] = 0; // CMY = 0
  1471. }
  1472.  
  1473. static void
  1474. MatchOne_XYZ_Gray (UInt16* chan)
  1475. {
  1476.     chan[0] = FractToUInt16(chan[1]); // gray = Y
  1477. }
  1478.  
  1479. static void
  1480. MatchOne_Gray_XYZ (UInt16* chan)
  1481. {
  1482.     double X,Y,Z;
  1483.     
  1484.     Y = UInt16ToDoub(chan[0]);
  1485.     X = Y * 0.96417;
  1486.     Z = Y * 0.82489;
  1487.     
  1488.     chan[0] = DoubToFract(X);
  1489.     chan[1] = DoubToFract(Y);
  1490.     chan[2] = DoubToFract(Z);
  1491. }
  1492.  
  1493.